{
  "nbformat": 4,
  "nbformat_minor": 0,
  "metadata": {
    "colab": {
      "name": "feature_columns.ipynb",
      "version": "0.3.2",
      "provenance": [],
      "private_outputs": true,
      "collapsed_sections": [],
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "rNdWfPXCjTjY"
      },
      "source": [
        "##### Copyright 2019 The TensorFlow Authors."
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "cellView": "form",
        "colab_type": "code",
        "id": "I1dUQ0GejU8N",
        "colab": {}
      },
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "c05P9g5WjizZ"
      },
      "source": [
        "# 对结构化数据进行分类"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "zofH_gCzgplN"
      },
      "source": [
        "<table class=\"tfo-notebook-buttons\" align=\"left\">\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://tensorflow.google.cn/tutorials/structured_data/feature_columns\">\n",
        "    <img src=\"https://tensorflow.google.cn/images/tf_logo_32px.png\" />\n",
        "    在 tensorflow.google.cn 上查看</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://colab.research.google.com/github/tensorflow/docs/blob/master/site/zh-cn/tutorials/structured_data/feature_columns.ipynb\">\n",
        "    <img src=\"https://tensorflow.google.cn/images/colab_logo_32px.png\" />\n",
        "    在 Google Colab 运行</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a target=\"_blank\" href=\"https://github.com/tensorflow/docs/blob/master/site/zh-cn/tutorials/structured_data/feature_columns.ipynb\">\n",
        "    <img src=\"https://tensorflow.google.cn/images/GitHub-Mark-32px.png\" />\n",
        "    在 Github 上查看源代码</a>\n",
        "  </td>\n",
        "  <td>\n",
        "    <a href=\"https://storage.googleapis.com/tensorflow_docs/docs/site/zh-cn/tutorials/structured_data/feature_columns.ipynb\"><img src=\"https://tensorflow.google.cn/images/download_logo_32px.png\" />下载此 notebook</a>\n",
        "  </td>\n",
        "</table>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Zz7U1iGCwp7T",
        "colab_type": "text"
      },
      "source": [
        "Note: 我们的 TensorFlow 社区翻译了这些文档。因为社区翻译是尽力而为， 所以无法保证它们是最准确的，并且反映了最新的\n",
        "[官方英文文档](https://www.tensorflow.org/?hl=en)。如果您有改进此翻译的建议， 请提交 pull request 到\n",
        "[tensorflow/docs](https://github.com/tensorflow/docs) GitHub 仓库。要志愿地撰写或者审核译文，请加入\n",
        "[docs-zh-cn@tensorflow.org Google Group](https://groups.google.com/a/tensorflow.org/forum/#!forum/docs-zh-cn)。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "K1y4OHpGgss7"
      },
      "source": [
        "本教程演示了如何对结构化数据进行分类（例如，CSV 中的表格数据）。我们将使用 [Keras](https://tensorflow.google.cn/guide/keras)  来定义模型，将[特征列（feature columns）](https://tensorflow.google.cn/guide/feature_columns) 作为从 CSV 中的列（columns）映射到用于训练模型的特征（features）的桥梁。本教程包括了以下内容的完整代码：\n",
        "\n",
        "* 用 [Pandas](https://pandas.pydata.org/) 导入 CSV 文件。\n",
        "* 用 [tf.data](https://tensorflow.google.cn/guide/datasets) 建立了一个输入流水线（pipeline），用于对行进行分批（batch）和随机排序（shuffle）。\n",
        "* 用特征列将 CSV 中的列映射到用于训练模型的特征。\n",
        "* 用 Keras 构建，训练并评估模型。\n",
        "\n",
        "## 数据集\n",
        "\n",
        "我们将使用一个小型 [数据集](https://archive.ics.uci.edu/ml/datasets/heart+Disease)，该数据集由克利夫兰心脏病诊所基金会（Cleveland Clinic Foundation for Heart Disease）提供。CSV 中有几百行数据。每行描述了一个病人（patient），每列描述了一个属性（attribute）。我们将使用这些信息来预测一位病人是否患有心脏病，这是在该数据集上的二分类任务。\n",
        "\n",
        "下面是该数据集的[描述](https://archive.ics.uci.edu/ml/machine-learning-databases/heart-disease/heart-disease.names)。 请注意，有数值（numeric）和类别（categorical）类型的列。\n",
        "\n",
        ">列| 描述| 特征类型 | 数据类型\n",
        ">------------|--------------------|----------------------|-----------------\n",
        ">Age | 年龄以年为单位 | Numerical | integer\n",
        ">Sex | （1 = 男；0 = 女） | Categorical | integer\n",
        ">CP | 胸痛类型（0，1，2，3，4）| Categorical | integer\n",
        ">Trestbpd | 静息血压（入院时，以mm Hg计） | Numerical | integer\n",
        ">Chol | 血清胆固醇（mg/dl） | Numerical | integer\n",
        ">FBS |（空腹血糖> 120 mg/dl）（1 = true；0 = false）| Categorical | integer\n",
        ">RestECG | 静息心电图结果（0，1，2）| Categorical | integer\n",
        ">Thalach | 达到的最大心率 | Numerical | integer\n",
        ">Exang | 运动诱发心绞痛（1 =是；0 =否）| Categorical | integer\n",
        ">Oldpeak | 与休息时相比由运动引起的 ST 节段下降|Numerical | integer\n",
        ">Slope | 在运动高峰 ST 段的斜率 | Numerical | float\n",
        ">CA | 荧光透视法染色的大血管动脉（0-3）的数量 | Numerical | integer\n",
        ">Thal | 3 =正常；6 =固定缺陷；7 =可逆缺陷 | Categorical | string\n",
        ">Target | 心脏病诊断（1 = true；0 = false） | Classification | integer"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "VxyBFc_kKazA"
      },
      "source": [
        "## 导入 TensorFlow 和其他库"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "LuOWVJBz8a6G",
        "colab": {}
      },
      "source": [
        "!pip install sklearn"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "9dEreb4QKizj",
        "colab": {}
      },
      "source": [
        "from __future__ import absolute_import, division, print_function, unicode_literals\n",
        "\n",
        "import numpy as np\n",
        "import pandas as pd\n",
        "\n",
        "try:\n",
        "  # Colab only\n",
        "  %tensorflow_version 2.x\n",
        "except Exception:\n",
        "    pass\n",
        "import tensorflow as tf\n",
        "\n",
        "from tensorflow import feature_column\n",
        "from tensorflow.keras import layers\n",
        "from sklearn.model_selection import train_test_split"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "KCEhSZcULZ9n"
      },
      "source": [
        "## 使用 Pandas 创建一个 dataframe\n",
        "\n",
        "[Pandas](https://pandas.pydata.org/) 是一个 Python 库，它有许多有用的实用程序，用于加载和处理结构化数据。我们将使用 Pandas 从 URL下载数据集，并将其加载到 dataframe 中。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "REZ57BXCLdfG",
        "colab": {}
      },
      "source": [
        "URL = 'https://storage.googleapis.com/applied-dl/heart.csv'\n",
        "dataframe = pd.read_csv(URL)\n",
        "dataframe.head()"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "u0zhLtQqMPem"
      },
      "source": [
        "## 将 dataframe 拆分为训练、验证和测试集\n",
        "\n",
        "我们下载的数据集是一个 CSV 文件。 我们将其拆分为训练、验证和测试集。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "YEOpw7LhMYsI",
        "colab": {}
      },
      "source": [
        "train, test = train_test_split(dataframe, test_size=0.2)\n",
        "train, val = train_test_split(train, test_size=0.2)\n",
        "print(len(train), 'train examples')\n",
        "print(len(val), 'validation examples')\n",
        "print(len(test), 'test examples')"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "84ef46LXMfvu"
      },
      "source": [
        "## 用 tf.data 创建输入流水线\n",
        "\n",
        "接下来，我们将使用 [tf.data](https://tensorflow.google.cn/guide/datasets) 包装 dataframe。这让我们能将特征列作为一座桥梁，该桥梁将 Pandas dataframe 中的列映射到用于训练模型的特征。如果我们使用一个非常大的 CSV 文件（非常大以至于它不能放入内存），我们将使用 tf.data 直接从磁盘读取它。本教程不涉及这一点。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "NkcaMYP-MsRe",
        "colab": {}
      },
      "source": [
        "# 一种从 Pandas Dataframe 创建 tf.data 数据集的实用程序方法（utility method）\n",
        "def df_to_dataset(dataframe, shuffle=True, batch_size=32):\n",
        "  dataframe = dataframe.copy()\n",
        "  labels = dataframe.pop('target')\n",
        "  ds = tf.data.Dataset.from_tensor_slices((dict(dataframe), labels))\n",
        "  if shuffle:\n",
        "    ds = ds.shuffle(buffer_size=len(dataframe))\n",
        "  ds = ds.batch(batch_size)\n",
        "  return ds"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "CXbbXkJvMy34",
        "colab": {}
      },
      "source": [
        "batch_size = 5 # 小批量大小用于演示\n",
        "train_ds = df_to_dataset(train, batch_size=batch_size)\n",
        "val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)\n",
        "test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "qRLGSMDzM-dl"
      },
      "source": [
        "## 理解输入流水线\n",
        "\n",
        "现在我们已经创建了输入流水线，让我们调用它来查看它返回的数据的格式。 我们使用了一小批量大小来保持输出的可读性。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "CSBo3dUVNFc9",
        "colab": {}
      },
      "source": [
        "for feature_batch, label_batch in train_ds.take(1):\n",
        "  print('Every feature:', list(feature_batch.keys()))\n",
        "  print('A batch of ages:', feature_batch['age'])\n",
        "  print('A batch of targets:', label_batch )"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "OT5N6Se-NQsC"
      },
      "source": [
        "我们可以看到数据集返回了一个字典，该字典从列名称（来自 dataframe）映射到 dataframe 中行的列值。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ttIvgLRaNoOQ"
      },
      "source": [
        "## 演示几种特征列\n",
        "TensorFlow 提供了多种特征列。本节中，我们将创建几类特征列，并演示特征列如何转换 dataframe 中的列。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "mxwiHFHuNhmf",
        "colab": {}
      },
      "source": [
        "# 我们将使用该批数据演示几种特征列\n",
        "example_batch = next(iter(train_ds))[0]"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "0wfLB8Q3N3UH",
        "colab": {}
      },
      "source": [
        "# 用于创建一个特征列\n",
        "# 并转换一批次数据的一个实用程序方法\n",
        "def demo(feature_column):\n",
        "  feature_layer = layers.DenseFeatures(feature_column)\n",
        "  print(feature_layer(example_batch).numpy())"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "Q7OEKe82N-Qb"
      },
      "source": [
        "### 数值列\n",
        "一个特征列的输出将成为模型的输入（使用上面定义的 demo 函数，我们将能准确地看到 dataframe 中的每列的转换方式）。 [数值列（numeric column）](https://tensorflow.google.cn/api_docs/python/tf/feature_column/numeric_column) 是最简单的列类型。它用于表示实数特征。使用此列时，模型将从 dataframe 中接收未更改的列值。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "QZTZ0HnHOCxC",
        "colab": {}
      },
      "source": [
        "age = feature_column.numeric_column(\"age\")\n",
        "demo(age)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "7a6ddSyzOKpq"
      },
      "source": [
        "在这个心脏病数据集中，dataframe 中的大多数列都是数值列。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "IcSxUoYgOlA1"
      },
      "source": [
        "### 分桶列\n",
        "通常，您不希望将数字直接输入模型，而是根据数值范围将其值分成不同的类别。考虑代表一个人年龄的原始数据。我们可以用 [分桶列（bucketized column）](https://tensorflow.google.cn/api_docs/python/tf/feature_column/bucketized_column)将年龄分成几个分桶（buckets），而不是将年龄表示成数值列。请注意下面的 one-hot 数值表示每行匹配的年龄范围。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "wJ4Wt3SAOpTQ",
        "colab": {}
      },
      "source": [
        "age_buckets = feature_column.bucketized_column(age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])\n",
        "demo(age_buckets)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "r1tArzewPb-b"
      },
      "source": [
        "### 分类列\n",
        "在此数据集中，thal 用字符串表示（如 'fixed'，'normal'，或 'reversible'）。我们无法直接将字符串提供给模型。相反，我们必须首先将它们映射到数值。分类词汇列（categorical vocabulary columns）提供了一种用 one-hot 向量表示字符串的方法（就像您在上面看到的年龄分桶一样）。词汇表可以用 [categorical_column_with_vocabulary_list](https://tensorflow.google.cn/api_docs/python/tf/feature_column/categorical_column_with_vocabulary_list) 作为 list 传递，或者用 [categorical_column_with_vocabulary_file](https://tensorflow.google.cn/api_docs/python/tf/feature_column/categorical_column_with_vocabulary_file) 从文件中加载。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "DJ6QnSHkPtOC",
        "colab": {}
      },
      "source": [
        "thal = feature_column.categorical_column_with_vocabulary_list(\n",
        "      'thal', ['fixed', 'normal', 'reversible'])\n",
        "\n",
        "thal_one_hot = feature_column.indicator_column(thal)\n",
        "demo(thal_one_hot)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "dxQloQ9jOoXL"
      },
      "source": [
        "在更复杂的数据集中，许多列都是分类列（如 strings）。在处理分类数据时，特征列最有价值。尽管在该数据集中只有一列分类列，但我们将使用它来演示在处理其他数据集时，可以使用的几种重要的特征列。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "LEFPjUr6QmwS"
      },
      "source": [
        "### 嵌入列\n",
        "假设我们不是只有几个可能的字符串，而是每个类别有数千（或更多）值。 由于多种原因，随着类别数量的增加，使用 one-hot 编码训练神经网络变得不可行。我们可以使用嵌入列来克服此限制。[嵌入列（embedding column）](https://tensorflow.google.cn/api_docs/python/tf/feature_column/embedding_column)将数据表示为一个低维度密集向量，而非多维的 one-hot 向量，该低维度密集向量可以包含任何数，而不仅仅是 0 或 1。嵌入的大小（在下面的示例中为 8）是必须调整的参数。\n",
        "\n",
        "关键点：当分类列具有许多可能的值时，最好使用嵌入列。我们在这里使用嵌入列用于演示目的，为此您有一个完整的示例，以在将来可以修改用于其他数据集。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "hSlohmr2Q_UU",
        "colab": {}
      },
      "source": [
        "# 注意到嵌入列的输入是我们之前创建的类别列\n",
        "thal_embedding = feature_column.embedding_column(thal, dimension=8)\n",
        "demo(thal_embedding)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "urFCAvTVRMpB"
      },
      "source": [
        "### 经过哈希处理的特征列\n",
        "\n",
        "表示具有大量数值的分类列的另一种方法是使用 [categorical_column_with_hash_bucket](https://tensorflow.google.cn/api_docs/python/tf/feature_column/categorical_column_with_hash_bucket)。该特征列计算输入的一个哈希值，然后选择一个 `hash_bucket_size` 分桶来编码字符串。使用此列时，您不需要提供词汇表，并且可以选择使 hash_buckets 的数量远远小于实际类别的数量以节省空间。\n",
        "\n",
        "关键点：该技术的一个重要缺点是可能存在冲突，不同的字符串被映射到同一个范围。实际上，无论如何，经过哈希处理的特征列对某些数据集都有效。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "YHU_Aj2nRRDC",
        "colab": {}
      },
      "source": [
        "thal_hashed = feature_column.categorical_column_with_hash_bucket(\n",
        "      'thal', hash_bucket_size=1000)\n",
        "demo(feature_column.indicator_column(thal_hashed))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "fB94M27DRXtZ"
      },
      "source": [
        "### 组合的特征列\n",
        "将多种特征组合到一个特征中，称为[特征组合（feature crosses）](https://developers.google.com/machine-learning/glossary/#feature_cross)，它让模型能够为每种特征组合学习单独的权重。此处，我们将创建一个 age 和 thal 组合的新特征。请注意，`crossed_column` 不会构建所有可能组合的完整列表（可能非常大）。相反，它由 `hashed_column` 支持，因此您可以选择表的大小。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "oaPVERd9Rep6",
        "colab": {}
      },
      "source": [
        "crossed_feature = feature_column.crossed_column([age_buckets, thal], hash_bucket_size=1000)\n",
        "demo(feature_column.indicator_column(crossed_feature))"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "ypkI9zx6Rj1q"
      },
      "source": [
        "## 选择要使用的列\n",
        "我们已经了解了如何使用几种类型的特征列。 现在我们将使用它们来训练模型。本教程的目标是向您展示使用特征列所需的完整代码（例如，机制）。我们任意地选择了几列来训练我们的模型。\n",
        "\n",
        "关键点：如果您的目标是建立一个准确的模型，请尝试使用您自己的更大的数据集，并仔细考虑哪些特征最有意义，以及如何表示它们。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "4PlLY7fORuzA",
        "colab": {}
      },
      "source": [
        "feature_columns = []\n",
        "\n",
        "# 数值列\n",
        "for header in ['age', 'trestbps', 'chol', 'thalach', 'oldpeak', 'slope', 'ca']:\n",
        "  feature_columns.append(feature_column.numeric_column(header))\n",
        "\n",
        "# 分桶列\n",
        "age_buckets = feature_column.bucketized_column(age, boundaries=[18, 25, 30, 35, 40, 45, 50, 55, 60, 65])\n",
        "feature_columns.append(age_buckets)\n",
        "\n",
        "# 分类列\n",
        "thal = feature_column.categorical_column_with_vocabulary_list(\n",
        "      'thal', ['fixed', 'normal', 'reversible'])\n",
        "thal_one_hot = feature_column.indicator_column(thal)\n",
        "feature_columns.append(thal_one_hot)\n",
        "\n",
        "# 嵌入列\n",
        "thal_embedding = feature_column.embedding_column(thal, dimension=8)\n",
        "feature_columns.append(thal_embedding)\n",
        "\n",
        "# 组合列\n",
        "crossed_feature = feature_column.crossed_column([age_buckets, thal], hash_bucket_size=1000)\n",
        "crossed_feature = feature_column.indicator_column(crossed_feature)\n",
        "feature_columns.append(crossed_feature)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "M-nDp8krS_ts"
      },
      "source": [
        "### 建立一个新的特征层\n",
        "现在我们已经定义了我们的特征列，我们将使用[密集特征（DenseFeatures）](https://tensorflow.google.cn/versions/r2.0/api_docs/python/tf/keras/layers/DenseFeatures)层将特征列输入到我们的 Keras 模型中。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "6o-El1R2TGQP",
        "colab": {}
      },
      "source": [
        "feature_layer = tf.keras.layers.DenseFeatures(feature_columns)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "8cf6vKfgTH0U"
      },
      "source": [
        "之前，我们使用一个小批量大小来演示特征列如何运转。我们将创建一个新的更大批量的输入流水线。"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "gcemszoGSse_",
        "colab": {}
      },
      "source": [
        "batch_size = 32\n",
        "train_ds = df_to_dataset(train, batch_size=batch_size)\n",
        "val_ds = df_to_dataset(val, shuffle=False, batch_size=batch_size)\n",
        "test_ds = df_to_dataset(test, shuffle=False, batch_size=batch_size)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "bBx4Xu0eTXWq"
      },
      "source": [
        "## 创建，编译和训练模型"
      ]
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "_YJPPb3xTPeZ",
        "colab": {}
      },
      "source": [
        "model = tf.keras.Sequential([\n",
        "  feature_layer,\n",
        "  layers.Dense(128, activation='relu'),\n",
        "  layers.Dense(128, activation='relu'),\n",
        "  layers.Dense(1, activation='sigmoid')\n",
        "])\n",
        "\n",
        "model.compile(optimizer='adam',\n",
        "              loss='binary_crossentropy',\n",
        "              metrics=['accuracy'],\n",
        "              run_eagerly=True)\n",
        "\n",
        "model.fit(train_ds,\n",
        "          validation_data=val_ds,\n",
        "          epochs=5)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "code",
      "metadata": {
        "colab_type": "code",
        "id": "GnFmMOW0Tcaa",
        "colab": {}
      },
      "source": [
        "loss, accuracy = model.evaluate(test_ds)\n",
        "print(\"Accuracy\", accuracy)"
      ],
      "execution_count": 0,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "3bdfbq20V6zu"
      },
      "source": [
        "关键点：通常使用更大更复杂的数据集进行深度学习，您将看到最佳结果。使用像这样的小数据集时，我们建议使用决策树或随机森林作为强有力的基准。本教程的目的不是训练一个准确的模型，而是演示处理结构化数据的机制，这样，在将来使用自己的数据集时，您有可以使用的代码作为起点。"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "colab_type": "text",
        "id": "SotnhVWuHQCw"
      },
      "source": [
        "### 下一步\n",
        "了解有关分类结构化数据的更多信息的最佳方法是亲自尝试。我们建议寻找另一个可以使用的数据集，并使用和上面相似的代码，训练一个模型，对其分类。要提高准确率，请仔细考虑模型中包含哪些特征，以及如何表示这些特征。"
      ]
    }
  ]
}
